<?php declare(strict_types=1);

namespace WanZ\App\Utils;

use Exception;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Redis\Redis;

/**
 * Class ClientUserCache
 * @package WanZ\App\Utils
 *
 */
trait ClientUserCache
{
    private $cacheKey = 'clientUser:';

    /**
     * 设置微信登陆后获取到的密钥值
     *
     * @param $key
     * @param array $value
     * @return bool
     * @throws Exception
     */
    public function wxSessionKeySet($key, array $value): bool
    {
        $kv = $this->getWxBaseConfig('s_key');
        $key = $kv['key'] . $key;

        return $this->setData($key, $value, $kv['expire']);
    }

    /**
     * 获取微信登陆后获取到的密钥值
     *
     * @param $key
     * @return array
     * @throws Exception
     */
    public function wxSessionKeyGet($key): array
    {
        $kv = $this->getWxBaseConfig('s_key');
        $key = $kv['key'] . $key;

        return $this->getData($key);
    }

    /**
     * 删除 sessionKey
     *
     * @param $key
     * @return mixed
     * @throws Exception
     */
    public function wxSessionKeyDel($key)
    {
        $kv = $this->getWxBaseConfig('s_key');
        $key = $kv['key'] . $key;

        return $this->delOneData($key);
    }

    /**
     * 设置通过阿里小程序登陆成功后从阿里处获取到的值
     *
     * @param $key
     * @param array $value
     * @return bool
     * @throws Exception
     */
    public function aliLoginSuccessInfoSet($key, array $value): bool
    {
        $kv = $this->getAliBaseConfig('login');
        $key = $kv['key'] . $key;

        return $this->setData($key, $value, $kv['expire']);
    }

    /**
     * 获取通过阿里小程序登陆成功后从阿里处获取到的值
     *
     * @param $key
     * @return array
     * @throws Exception
     */
    public function aliLoginSuccessInfoGet($key): array
    {
        $kv = $this->getAliBaseConfig('login');
        $key = $kv['key'] . $key;

        return $this->getData($key);
    }

    /**
     * 设置redis缓存数据
     *
     * @param string $key
     * @param array $data
     * @param int $expire 过期时间默认30分钟
     * @return bool
     */
    public function setData(string $key, array $data, int $expire = 1800): bool
    {
        $key = $this->cacheKey . $key;
        $this->getRedis()->hMSet($key, ['value' => json_encode($data, JSON_UNESCAPED_SLASHES)]);
        $this->getRedis()->expire($key, $expire);
        return true;
    }

    /**
     * 获取redis缓存数据
     *
     * @param string $key
     * @return array
     */
    public function getData(string $key): array
    {
        $key = $this->cacheKey . $key;
        $value = $this->getRedis()->hGetAll($key);

        if (empty($value)) {
            return [];
        }

        return json_decode($value['value'], true);
    }

    /**
     * 删除一条缓存数据
     *
     * @param string $key1
     * @param string|null $key2
     * @param string|null $key3
     * @return mixed
     */
    public function delOneData(string  $key1, string $key2 = null, string $key3 = null)
    {
        $key1 = $this->cacheKey . $key1;
        return $this->getRedis()->del($key1, $key2, $key3);
    }

    /**
     * 删除多个缓存数据
     *
     * @param string $key
     * @param string $hashKey1
     * @param string|null $hashKey2
     * @param string|null $hashKeyN
     * @return mixed
     */
    public function delMultiData(string $key, string $hashKey1, string $hashKey2 = null, string $hashKeyN = null)
    {
        $key = $this->cacheKey . $key;
        return $this->getRedis()->hDel($key, $hashKey1, $hashKey2, $hashKeyN);
    }

    /**
     * 获取微信的基础配置文件
     * @return array | bool
     * @throws Exception
     */
    private function getWxBaseConfig(string $key)
    {
        $config = $this->getBaseConfig('wx');
        if (isset($config[$key])) {
            return $config[$key];
        }

        throw new Exception("微信的Redis配置有误：{$key}不存在");
    }

    /**
     * 获取阿里的基础配置文件
     *
     * @param string $key
     * @return false|mixed
     * @throws Exception
     */
    private function getAliBaseConfig(string $key)
    {
        $config = $this->getBaseConfig('ali');
        if (isset($config[$key])) {
            return $config[$key];
        }

        throw new Exception("阿里的Redis配置有误：{$key}不存在");
    }

    /**
     * 动态获取字段值
     *
     * @param $name
     * @return mixed
     * @throws Exception
     */
    public function __get($name)
    {
        $res = $this->getData($name);
        if (empty($res)) {
            throw new Exception('getCarUserRedisDataError: 获取用户失败，缓存数据为空');
        }

        if (!isset($res[$name])) {
            return '';
        }

        return $res[$name];
    }

    /**
     * 获取基础配置信息
     *
     * @param string $platformType
     * @return mixed
     */
    private function getBaseConfig(string $platformType)
    {
       return config("redis.car_user.{$platformType}");
    }

    /**
     * @return Pool
     */
    private function getRedis(): \Hyperf\Redis\Redis
    {
        $container = ApplicationContext::getContainer();
        return $container->get(\Hyperf\Redis\Redis::class);
    }
}
